/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package util;

import java.awt.Dimension;
import java.awt.Toolkit;
import java.awt.Window;
import java.awt.event.KeyEvent;
import java.util.*;
import javax.swing.*;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableColumnModel;
import javax.swing.tree.*;
import org.japura.gui.CheckList;
import org.japura.gui.model.DefaultListCheckModel;
import util.components.MyTreeModel;

/**
 *
 * @author Raul
 */
public class GestorComponenteVista {
    
    
    public GestorComponenteVista() {
    }
    
    //Codigo auxiliar utilizado cuando no funciona setLocationRelativeTo(null)
    public static void centrarVentana(Window window){
        Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
        window.setLocation(dim.width/2-window.getSize().width/2,
                dim.height/2-window.getSize().height/2);
    }
    
    public static Object getObjetoSeleccionado(JTree arbol){
        return arbol.getLastSelectedPathComponent();
    }
    
    public static void cargarArbolEstatico(JTree arbol, Object [] jerarquia) {
        DefaultMutableTreeNode raiz = procesarJerarquia(jerarquia);
//        arbol.setModel(new DefaultTreeModel(raiz));
        ((DefaultTreeModel) arbol.getModel()).setRoot(raiz);
    }
    
    public static DefaultMutableTreeNode procesarJerarquia(Object [] jerarquia) {
        DefaultMutableTreeNode padre = new DefaultMutableTreeNode(jerarquia[0]);
        DefaultMutableTreeNode child;
        for(int i=1; i<jerarquia.length; i++) {
            Object nodeSpecifier = jerarquia[i];
            if (nodeSpecifier instanceof Object[]) {  // Ie node with children
            child = procesarJerarquia((Object[])nodeSpecifier);
            } else {
                child = new DefaultMutableTreeNode(nodeSpecifier);
            }// Ie Leaf
            padre.add(child);
        }
        return padre;
    }

    public static void agregarNodoArbol(JTree arbol, Object padre, Object hoja) {
        ((MyTreeModel)arbol.getModel()).insertNodeInto(hoja, padre);
    }
    
    public static void quitarNodoArbol(JTree arbol, Object hoja) {
        arbol.setSelectionRow(-1);
        ((MyTreeModel)arbol.getModel()).removeNodeFromParent(hoja);
    }
    
    public static void crearModeloArbol(JTree arbol, TreeModel model) {
        ImageIcon leafIcon = 
                new ImageIcon(GestorComponenteVista.class.getResource("/resources/bullet_sparkle.png"));
        crearModeloArbol(arbol, model, leafIcon);
    }

    public static void crearModeloArbol(JTree arbol, TreeModel model, ImageIcon leafIcon) {
        arbol.setModel(model);
        setRenderer(arbol, leafIcon);
    }

    public static void setRenderer(JTree arbol, ImageIcon leafIcon) {
        DefaultTreeCellRenderer renderer = new DefaultTreeCellRenderer();
        renderer.setLeafIcon(leafIcon);
        renderer.setOpenIcon(
                new ImageIcon(GestorComponenteVista.class.getResource("/resources/folder-open.png")));
        renderer.setClosedIcon(
                new ImageIcon(GestorComponenteVista.class.getResource("/resources/folder-closed.png")));
        arbol.setCellRenderer(renderer);
    }
    
    public static void setDefaultRenderer(JTree arbol) {
        ImageIcon leafIcon = 
                new ImageIcon(GestorComponenteVista.class.getResource("/resources/bullet_sparkle.png"));
        setRenderer(arbol, leafIcon);
    }

    /**
     *Devuelve una lista con todos los objetos cargados en el arbol que son HOJAS 
     *
     * @param arbol
     * @return 
     */
    public static List getObjetosEnArbol(JTree arbol) {
        TreeModel model = arbol.getModel();
        ArrayList lista = new ArrayList();
        agregarHijosALista(model, lista, model.getRoot());
        return lista;
    }
    
    private static void agregarHijosALista(TreeModel model, ArrayList lista, Object nodo) {
        for (int i=0; i<model.getChildCount(nodo);i++){
            Object hijo = model.getChild(nodo, i);
            if (model.isLeaf(hijo)){
                lista.add(hijo);
            } else {
                agregarHijosALista(model, lista, hijo);
            }
        }
    }

    /**expande todos los nodos solo funciona para MyTreeModel
     * 
     * @param arbol 
     */
    public static void expandirArbol(JTree arbol){
        expandirNodo(arbol, arbol.getModel().getRoot());
    }
    
    public static void expandirNodo(JTree arbol, Object nodo) {
        if (!arbol.getModel().isLeaf(nodo)) {
            arbol.expandPath(new TreePath(((MyTreeModel)arbol.getModel()).getPathToRoot(nodo)));
            
            int childCount = arbol.getModel().getChildCount(nodo);
            for (int i = 0 ; i<childCount ; i++) {
                expandirNodo(arbol, arbol.getModel().getChild(nodo, i));
            }
        }
        
        
    }
    
    /**Devuelve verdadero si el objeto seleccionado es una hoja. Antes se debe
     * consultar si hay algun objeto seleccionado
     * 
     * @param arbol
     * @return 
     */
    public static boolean isHojaSeleccionada(JTree arbol) {
        return arbol.getModel().isLeaf(getObjetoSeleccionado(arbol));
    }

    
    /** Carga el <code>combo</code> con la lista de <code>datos</code>
     * 
     * @param combo el combo donde se cargaran los datos
     * @param datos la lista de datos que se cargaran en el combo
     */
    public static void cargarCombo(JComboBox combo, Collection datos){
        combo.setModel(crearNuevoModeloCombo());
        agregarDatoCombo(combo, null);
        Iterator ite= datos.iterator();
        while(ite.hasNext()){
            Object dato= ite.next();
            agregarDatoCombo(combo, dato);
       }
    }
    
    /** Carga el <code>combo</code> con el vector de <code>datos</code>
     * 
     * @param combo el combo donde se cargaran los datos
     * @param datos el vector de datos que se cargaran en el combo
     */
    public static void cargarCombo(JComboBox combo, Object[] datos){
        combo.setModel(crearNuevoModeloCombo());
        agregarDatoCombo(combo, null);
        for (Object dato : datos)
            agregarDatoCombo(combo, dato);
    }
    
    public static void cargarCombo(JComboBox combo, String[] datos){
        combo.setModel(crearNuevoModeloCombo());
        agregarDatoCombo(combo, "");
        for (Object dato : datos)
            agregarDatoCombo(combo, dato);
    }
    
    /**Crea un  modelo de combo default
     * 
     * @return el modelo de combo creado
     */
    public static DefaultComboBoxModel crearNuevoModeloCombo() {
        return new DefaultComboBoxModel();
    }
    
    /**Agrega un <code>dato</code> al final del <code>combo</code>
     * 
     * @param combo el combo donde se agregara el dato
     * @param dato el dato a agregarse en el combo
     */
    public static void agregarDatoCombo(JComboBox combo, Object dato) {
        DefaultComboBoxModel modelo=(DefaultComboBoxModel) combo.getModel();
        modelo.addElement(dato);
    }
    
    
    public static void quitarDatosCombo(JComboBox combo, Collection datos){
        Iterator ite = datos.iterator();
        while(ite.hasNext()){
            quitarDatoCombo(combo, ite.next());
        }
    }
    
    public static void quitarDatoCombo(JComboBox combo, Object dato){
        combo.removeItem(dato);
    }
    
    /** Carga la <code>lista</code> con la coleccion de <code>datos</code>
     * 
     * @param lista lista donde se cargaran los datos
     * @param datos la coleccion de datos que se cargaran en la lista
     */    
    public static void cargarLista(JList lista, Collection datos){
        lista.setModel(new DefaultListModel());
        Iterator ite = datos.iterator();
        while(ite.hasNext()){
            agregarDatoLista(lista, ite.next());
        }
    }
    
    public static void cargarLista(CheckList lista, Collection datos) {
        DefaultListCheckModel model = new DefaultListCheckModel();
        lista.setModel(model);
        Iterator i = datos.iterator();
        while (i.hasNext()){
            model.addElement(i.next());
        }
    }
    
    public static void setearSeleccionadosCheckList(CheckList lista, Collection seleccionados) {
        DefaultListCheckModel model = (DefaultListCheckModel)lista.getModel();
        model.removeChecks();//quizas no necesario, ¿que pasa con coleccion vacia?
        model.setCheck(seleccionados.toArray(new Object[0]));
    }

    public static void agregarDatosLista(JList lista, Collection datos){
        Iterator ite = datos.iterator();
        while(ite.hasNext()){
            agregarDatoLista(lista, ite.next());
        }
    }
    
    /**Agrega un <code>dato</code> al final de la <code>lista</code>
     * 
     * @param lista lista donde se agregara el dato
     * @param dato el dato a agregarse en la lista
     */
    public static void agregarDatoLista(JList lista, Object dato) {
        DefaultListModel modelo= (DefaultListModel) lista.getModel();
        modelo.addElement(dato);
    }
    
    public static List getObjetosEnLista(JList lista){
        return Arrays.asList(
                ((DefaultListModel)lista.getModel()).toArray());
    }
    
    /**Devuelve solo los objetos seleccionados
     * 
     * @param lista
     * @return 
     */
    public static List getObjetosEnLista(CheckList lista){
        return ((DefaultListCheckModel)lista.getModel()).getCheckeds();
    }

    /**Elimina el dato de la <code>lista</code> que se encuentra en la <code>posicion</code> indicada
     * 
     * @param lista la lista de donde se eliminara el dato
     * @param indice la posicion del del dato que sera eliminado
     */
    public static void quitarDatoLista(JList lista, int indice) {
        DefaultListModel modelo=(DefaultListModel) lista.getModel();
        modelo.remove(indice);
    }
    
    /**
     * Devuelve verdadero si el item se encuentra cargado en la lista
     * @param lista
     * @param item
     * @return 
     */
    public static boolean contiene(JList lista, Object item) {
        return ((DefaultListModel) lista.getModel()).contains(item);
    }
    
    /**Crea un modelo de tabla vacia y carga los titulos
     * 
     * @param tabla
     * @param titulos 
     */
    public static void cargarTitulosTabla(JTable tabla, Object[] titulos){
        tabla.setModel(crearModeloTablaNoEditable(titulos, 0));
    }
    
    public static void cargarTitulosTabla(JTable tabla, Object[] titulos, int[] anchos){
        tabla.setModel(crearModeloTablaNoEditable(titulos, 0));
        setAnchosDeColumna(tabla, anchos);
    }
    
    /**Devuelve el indice de la fila seleccionada en la tabla o -1 si no 
     * se selecciono ninguna fila
     * 
     * @param tabla la tabla de donde se toma la seleccion
     * @return el indice de la fila seleccionada
     */
    public static  int filaSeleccionada(JTable tabla) {
        return tabla.getSelectedRow();
    }
        
    /** Agrega una <code>fila</code> al final de la <code>tabla</code>
     * 
     * @param tabla la tabla donde se agregara la fila
     * @param fila los elementos de cada columna de la fila a agregar
     */
    public static void agregarFilaTabla(JTable tabla, Object[] fila) {
        ((DefaultTableModel) tabla.getModel()).addRow(fila);
    }
    
    public static void eliminarFilaTabla(JTable tabla, int row){
        ((DefaultTableModel) tabla.getModel()).removeRow(tabla.convertRowIndexToModel(row));
    }
    
    /** Crea un nuevo modelo de tabla no editable
     * 
     * @param titulo los encabezados de cada columna
     * @param cantFila la cantidad de filas inicial de la tabla
     */
    public static DefaultTableModel crearModeloTablaNoEditable(Object[] titulo, int cantFila) {
        return new DefaultTableModel(titulo,cantFila){
            @Override
            public boolean isCellEditable(int rowIndex, int columnIndex) {
                return false;
            }
        };
    }
    
    /**Devuelve el objeto que corresponde a la fila seleccionada en la tabla
     * 
     * @param tabla
     * @return el objeto seleccionado
     */
    public static Object getObjetoSeleccionado(JTable tabla){
        return tabla.getModel().getValueAt(tabla.convertRowIndexToModel(filaSeleccionada(tabla)), 0);
    }
    
    public static List getObjetosEnTabla(JTable tabla){
        DefaultTableModel model = (DefaultTableModel) tabla.getModel();
        ArrayList lista = new ArrayList();
        for (int i = 0; i< model.getRowCount();i++){
            lista.add(model.getValueAt(i, 0));
        }
        return lista;
    }
    
    /**Setea el ancho de cada columna de la tabla
     * La primera columna no se redimensiona
     * Ancho aproximado = 8 por letra.
     * Ej: En una celda de ancho 40 entran aprox 5 letras
     * 
     * @param tabla
     * @param anchos el ancho minimo de cada columna
     */
    public static void setAnchosDeColumna(JTable tabla, int [] anchos){
        TableColumnModel model = tabla.getColumnModel();
        model.getColumn(0).setPreferredWidth(anchos[0]);
        model.getColumn(0).setMinWidth(anchos[0]);
        model.getColumn(0).setMaxWidth(anchos[0]);
        for (int i = 1; i < anchos.length; i++) {
            model.getColumn(i).setPreferredWidth(anchos[i]);
            model.getColumn(i).setMinWidth(anchos[i]);
        }
    }
    
    public static java.awt.event.KeyAdapter crearNumeroKeyListener(){
        return new java.awt.event.KeyAdapter() {
    
            @Override
            public void keyTyped(java.awt.event.KeyEvent evt) {
                validarIngresoCaracterNumeroEntero(evt);
            }
        
            public void validarIngresoCaracterNumeroEntero(KeyEvent evt) {
                char caracter=evt.getKeyChar();
                //Si el caracter no es letra
                if(isLetra(caracter))
                    evt.consume();
            }
    
            private boolean isLetra(char caracter) {
                return (caracter<'0')||(caracter>'9');
            }
            
        };
    }
}
